package com.easylinkin.linkappapi.blockqueue;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.easylinkin.bases.redis.util.RedisUtil;
import com.easylinkin.linkappapi.alarm.service.AiAlarmCountService;
import com.easylinkin.linkappapi.blockqueue.constant.QueueKeyConstant;
import com.easylinkin.linkappapi.blockqueue.constant.QueueKeyConstant.QueueKeyEnum;
import com.easylinkin.linkappapi.circuit.service.IRailCircuitGivealarmService;
import com.easylinkin.linkappapi.circuit.service.IRailLinkappAiHostRecordService;
import com.easylinkin.linkappapi.device.service.ElectricyRecordsService;
import com.easylinkin.linkappapi.device.service.SprayRecordsService;
import com.easylinkin.linkappapi.device.service.WaterRecordsService;
import com.easylinkin.linkappapi.inspection.service.ElectricBoxRecordService;
import com.easylinkin.linkappapi.inspection.service.IRailLinkappElectricFireRecordService;
import com.easylinkin.linkappapi.lobar.service.GateService;
import com.easylinkin.linkappapi.location.service.ILinkappLocationDeviceService;
import com.easylinkin.linkappapi.machinery.service.ElevatorWorkRecordService;
import com.easylinkin.linkappapi.machinery.service.TowerCraneWorkRecordService;
import com.easylinkin.linkappapi.mechanical.service.CraneSafeMonitorService;
import com.easylinkin.linkappapi.mechanical.service.IEquipmentLocationService;
import com.easylinkin.linkappapi.openapi.dto.DatapushDTO;
import com.easylinkin.linkappapi.openapi.service.SystemDockingService;
import com.easylinkin.linkappapi.positioning.service.PositionAlarmService;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * @author xiaoyang
 * @version 1.0
 * @date 2023/08/15
 * @description 阻塞队列消费者
 */
@Slf4j
@Component
public class BlockingQueueConsumer implements Runnable{

  @Resource
  private RedisUtil redisUtil;

  @Resource
  private QueueManager queueManager;

  @Resource
  private PositionAlarmService positionAlarmService;

  @Resource
  private GateService gateService;

  @Resource
  private SprayRecordsService sprayRecordsService;

  @Resource
  private WaterRecordsService waterRecordsService;

  @Resource
  private ElectricyRecordsService electricyRecordsService;

  @Resource
  private TowerCraneWorkRecordService towerCraneWorkRecordService;

  @Resource
  private ElectricBoxRecordService electricBoxRecordService;

  @Resource
  private AiAlarmCountService aiAlarmCountService;

  @Resource
  private ElevatorWorkRecordService elevatorWorkRecordService;

  @Resource
  private SystemDockingService dockingService;

  @Resource
  private ILinkappLocationDeviceService linkappLocationDeviceService;


  @Resource
  private IRailCircuitGivealarmService railCircuitGivealarmService;

  @Resource
  private CraneSafeMonitorService craneSafeMonitorService;

  @Resource
  private IEquipmentLocationService equipmentLocationService;
  @Resource
  private IRailLinkappElectricFireRecordService railLinkappElectricFireRecordService;

  @Resource
  private IRailLinkappAiHostRecordService railLinkappAiHostRecordService;
  @Override
  public void run() {
    while (!Thread.currentThread().isInterrupted()) {
      try {
        List<String> allQueueKey = QueueKeyEnum.getAllQueueKey();
        for (String queueKey : allQueueKey) {
          comsumerQueue(queueKey,QueueKeyEnum.getThreadNameByQueueKey(queueKey));
        }
      } catch (Exception e) {
        log.error("BlockingQueueConsumer error:{}", e.getMessage());
        Thread.currentThread().interrupt();
      }
    }
  }

  public void comsumerQueue(String queueKey,String queueKeyName) {
    // 1.获取队列
//    log.debug("BlockingQueueConsumer {} queueKey:{}", this.getClass().getSimpleName(), queueKey);
    DatapushDTO data = null;
    try {
      data = queueManager.dequeue(queueKey);
      if (data != null) {
        // 3.核心业务逻辑
        long startTime = System.currentTimeMillis();
        coreBussiness(queueKey, data);
        long endTime = System.currentTimeMillis();
        log.info("comsumerQueue queueKey:{},queueKeyName:{},data:{},耗时:{}ms", queueKey,
            queueKeyName, data,
            endTime - startTime);
        // 存储消费成功次数 和 耗时 按天统计
        extracted(queueKey, startTime, endTime);
      }
    } catch (Exception e) {
      log.error("处理流水报错",e);
      log.error("comsumerQueue queueKey:{},queueKeyName:{}, error:{}", queueKey, queueKeyName,
          e.getMessage());
    }
  }

  /**
   * 统计消费成功次数 和 耗时
   * @param queueKey
   * @param startTime
   * @param endTime
   */
  // comsumerQueue:queueKey:success:20200101
  // comsumerQueue:queueKey:time:20200101
  private void extracted(String queueKey, long startTime, long endTime) {
    // 时间戳转换为天 2020-01-01
    String day = DateUtil.format(new Date(), "yyyyMMdd");
    String queueKeySuccess = "comsumerQueue:" + queueKey + ":success:" + day;
    String queueKeyTime = "comsumerQueue:" + queueKey + ":time:" + day;
    redisUtil.incr(queueKeySuccess, 1);
    redisUtil.incr(queueKeyTime, endTime - startTime);
    // 有效期3天
    redisUtil.expire(queueKeySuccess, 3 * 24 * 60 * 60 * 1000);
    redisUtil.expire(queueKeyTime, 3 * 24 * 60 * 60 * 1000);
  }

  /**
   * 核心业务逻辑
   * @param queueKey 队列key
   * @param data 流水数据
   */
  private void coreBussiness(String queueKey,DatapushDTO datapushDTO) throws JsonProcessingException {
    // 打印入参
    log.debug("BlockingQueueConsumer queueKey:{},data:{}", queueKey, JSON.toJSONString(datapushDTO));
    // 根据queueKey 执行相应的业务逻辑
    switch (queueKey) {
//      case QueueKeyConstant.AIR_CONDITIONING_ENERGY_CONSUMPTION_STATISTICS:
//        // 空调能耗统计
//        airconditionDeviceRecordService.separateMetering(datapushDTO);
//        break;
      case QueueKeyConstant.ELECTRONIC_FENCE_ALARM_FUNCTION:
        // 电子围栏报警功能
        positionAlarmService.checkPostionAlarm(datapushDTO);
        break;
      case QueueKeyConstant.GATE_FLOW_PROCESSING:
        // 闸机流水处理
        gateService.datapushHandler(datapushDTO);
        break;
      case QueueKeyConstant.SPRAY_FLOW_PROCESSING:
        // 喷淋流水处理
        sprayRecordsService.datapushHandler(datapushDTO);
        break;
      case QueueKeyConstant.WATER_FLOW_PROCESSING:
        // 用水流水处理
        waterRecordsService.datapushHandler(datapushDTO);
        break;
      case QueueKeyConstant.ELECTRICITY_FLOW_PROCESSING:
        // 用电流水处理
        electricyRecordsService.datapushHandler(datapushDTO);
        break;
      case QueueKeyConstant.TOWER_CRANE_FLOW_PROCESSING:
        // 塔机流水处理
        towerCraneWorkRecordService.datapushHandler(datapushDTO);
        break;
      case QueueKeyConstant.ELECTRRIC_BOX_FLOW_PROCESSING:
        // 配电箱流水处理
        electricBoxRecordService.datapushHandler(datapushDTO);
        break;
      case QueueKeyConstant.AI_CAMERA_WARNING_FLOW_STATISTICS:
        // ai相机预警流水统计
        //新 //
        railLinkappAiHostRecordService.datapushHandler(datapushDTO);
        //旧
        //aiAlarmCountService.datapushHandler(datapushDTO);
        break;
      case QueueKeyConstant.LIFT_FLOW_PROCESSING:
        // 升降机流水处理
        elevatorWorkRecordService.datapushHandler(datapushDTO);
        break;
      case QueueKeyConstant.LOCATION_PROCESSING:
        // 定位器流水处理
        linkappLocationDeviceService.datapushHandler(datapushDTO);
        break;
      case QueueKeyConstant.DATA_UPLOAD_TO_PROVINCIAL_HALL_SYSTEM:
        // 扬尘、塔机、升降机等设备数据上传到第三方对接系统
        dockingService.pushToSystemDockHandler(datapushDTO);
        break;
      case QueueKeyConstant.RAIL_CIRCUIT_GIVEALARM_FAULT_PROCESSING:
        railCircuitGivealarmService.datapushHandler(datapushDTO);
        break;
      case QueueKeyConstant.RAIL_CRANE_SAFETY_MONITORING:
        craneSafeMonitorService.datapushHandler(datapushDTO);
        break;
        //电气火灾
      case QueueKeyConstant.RAIL_CIRCUIT_DQHZ_PROCESSING:
        railLinkappElectricFireRecordService.datapushHandler(datapushDTO);
        break;
      case QueueKeyConstant.BEIDOU_LOCATION:
        // 北斗定位数据处理
        equipmentLocationService.datapushHandler(datapushDTO);
        break;
      default:
        break;
    }

  }
}
